/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * ListadosPanel.java
 *
 * Created on 26/11/2011, 10:29:01
 */
package org.tri.gui;

import furbelow.SpinningDial;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import javax.swing.DefaultComboBoxModel;
import javax.swing.Icon;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import org.tri.entity.*;
import org.tri.form.RegistroMovimientosExistencias;
import org.tri.gui.ListadosWorkers.*;
import org.tri.gui.view.ComprasView;
import org.tri.gui.view.VentasView;
import org.tri.gui.worker.*;
import org.tri.model.EntityTableModel;
import org.tri.model.TransaccionTableModel;

/**
 *
 * @author giaco
 */
public class ListadosPanel extends javax.swing.JPanel
        implements TableFillListener, TransientListener {

    /**Modelo de la tabla que muestra los resultados*/
    protected AbstractTableModel model;
    /** 
     * Lista de objetos que este panel recupero. Se necesita mantenerlo por
     * si es necesario removerlos del cache luego.
     */
    private Set<Object> objetosRecuperados;
    /**Combo Box del criterio de busqueda por productor o establecimiento*/
    private DefaultComboBoxModel criterioBusquedaComboBoxModel;
    /**Combo Box que define el tipo de lista que se requiere*/
    private DefaultComboBoxModel tipoListaComboBoxModel;
    /** Icono que indica que se esta realizando una busqueda. */
    private Icon loadingIcon;
    /** Frame padre de este panel. */
    private MainFrame frame;
    /**Productor con el cual trabajamos*/
    private Productor productor;
    /**Establecimiento con el cual trabajamos*/
    private Establecimiento establecimiento;
    /**Transaccion seleccionada del listado*/
    private Transaccion transaccion;
    /**Error durante la eliminacion*/
    private boolean errorTransit;
    /**Valor de la fila y columna seleccionada en la tabla de listados*/
    int row, column;

    /** Creates new form ListadosPanel */
    public ListadosPanel() {

        //inicializamos los comboBox
        criterioBusquedaComboBoxModel = new DefaultComboBoxModel( 
                new String[] { "Productor", "Establecimiento" } );

        tipoListaComboBoxModel = new DefaultComboBoxModel( new AbstractListadosWorker[] {
                    new VentasActualesListadosWorker(),
                    new ComprasActualesListadosWorker(),
                    new ExistenciasListadosWorker(),
                    new CaravanasListadosWorker( true ),
                    new CaravanasListadosWorker( false ),
                    new VentasHistoricasListadosWorker(),
                    new ComprasHistoricasListadosWorker(),
                    new VentasListadosWorker(),
                    new ComprasListadosWorker() } );

        //inicializamos el icono de loading
        loadingIcon = new SpinningDial( 20, 20, 10 );

        //inicializamos la lista de objetos recuperados
        objetosRecuperados = new HashSet<Object>();

        initComponents();

        jBGenerarListado.setVisible( false );

        resetDatePickers();

    }

    public ListadosPanel( MainFrame frame ) {
        this();

        this.frame = frame;

    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings ( "unchecked" )
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        jPMOpciones = new javax.swing.JPopupMenu();
        jMEliminar = new javax.swing.JMenu();
        jMIEliminarLista = new javax.swing.JMenuItem();
        jMIEliminarPermanente = new javax.swing.JMenuItem();
        jMIDeActuales = new javax.swing.JMenuItem();
        jMIDetalles = new javax.swing.JMenuItem();
        jPanel1 = new javax.swing.JPanel();
        jPresultados = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTResultados = new javax.swing.JTable();
        filler11 = new javax.swing.Box.Filler(new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 32767));
        filler12 = new javax.swing.Box.Filler(new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 32767));
        filler13 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 10), new java.awt.Dimension(0, 10), new java.awt.Dimension(32767, 10));
        jBGenerarListado = new javax.swing.JButton();
        jPlistas = new javax.swing.JPanel();
        jCBCriterioBusqueda = new javax.swing.JComboBox(criterioBusquedaComboBoxModel);
        jCBTipoLista = new javax.swing.JComboBox(tipoListaComboBoxModel);
        jBListar = new javax.swing.JButton();
        filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(20, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        jLWaitIcon = new javax.swing.JLabel();
        jXDPInicio = new org.jdesktop.swingx.JXDatePicker();
        jXDPFin = new org.jdesktop.swingx.JXDatePicker();

        jMEliminar.setText("Eliminar");

        jMIEliminarLista.setText("de la Lista");
        jMIEliminarLista.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMIEliminarListaActionPerformed(evt);
            }
        });
        jMEliminar.add(jMIEliminarLista);

        jMIEliminarPermanente.setText("Permanentemente");
        jMIEliminarPermanente.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMIEliminarPermanenteActionPerformed(evt);
            }
        });
        jMEliminar.add(jMIEliminarPermanente);

        jMIDeActuales.setText("de Actuales");
        jMIDeActuales.setToolTipText("Pasa una transaccion de Actual a Historica");
        jMIDeActuales.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMIDeActualesActionPerformed(evt);
            }
        });
        jMEliminar.add(jMIDeActuales);

        jPMOpciones.add(jMEliminar);

        jMIDetalles.setText("Detalles");
        jMIDetalles.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMIDetallesActionPerformed(evt);
            }
        });
        jPMOpciones.add(jMIDetalles);

        setLayout(new java.awt.BorderLayout());

        jPanel1.setLayout(new java.awt.GridBagLayout());

        jPresultados.setBorder(javax.swing.BorderFactory.createTitledBorder("Resultados"));
        jPresultados.setLayout(new java.awt.GridBagLayout());

        jTResultados.setComponentPopupMenu(jPMOpciones);
        jTResultados.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                jTResultadosMousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                jTResultadosMouseReleased(evt);
            }
        });
        jScrollPane1.setViewportView(jTResultados);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        jPresultados.add(jScrollPane1, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPresultados.add(filler11, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPresultados.add(filler12, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPresultados.add(filler13, gridBagConstraints);

        jBGenerarListado.setText("Generar Listado de Existencias");
        jBGenerarListado.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBGenerarListadoActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(5, 0, 0, 0);
        jPresultados.add(jBGenerarListado, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        jPanel1.add(jPresultados, gridBagConstraints);

        jPlistas.setBorder(javax.swing.BorderFactory.createTitledBorder("Listas"));
        jPlistas.setLayout(new java.awt.GridBagLayout());
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 15);
        jPlistas.add(jCBCriterioBusqueda, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 15);
        jPlistas.add(jCBTipoLista, gridBagConstraints);

        jBListar.setText("Listar");
        jBListar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBListarActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 8;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 15, 0, 0);
        jPlistas.add(jBListar, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 10;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        jPlistas.add(filler1, gridBagConstraints);

        jLabel1.setText("Por:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 15, 0, 0);
        jPlistas.add(jLabel1, gridBagConstraints);

        jLabel2.setText("Lista:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        jPlistas.add(jLabel2, gridBagConstraints);

        jLabel3.setText("Fecha Inicio:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 0;
        jPlistas.add(jLabel3, gridBagConstraints);

        jLabel4.setText("Fecha Fin:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 6;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 15, 0, 0);
        jPlistas.add(jLabel4, gridBagConstraints);

        jLWaitIcon.setMinimumSize(new java.awt.Dimension(20, 20));
        jLWaitIcon.setPreferredSize(new java.awt.Dimension(20, 20));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 9;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 0);
        jPlistas.add(jLWaitIcon, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 5;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0);
        jPlistas.add(jXDPInicio, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 7;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0);
        jPlistas.add(jXDPFin, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        jPanel1.add(jPlistas, gridBagConstraints);

        add(jPanel1, java.awt.BorderLayout.CENTER);
    }// </editor-fold>//GEN-END:initComponents

    private void jBListarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jBListarActionPerformed
        //realizamos las tareas de GUI para indicar que se inició la busqueda
        fireBusquedaTriggers( true );

        //recuperamos el worker seleccionado
        AbstractListadosWorker worker = (AbstractListadosWorker)jCBTipoLista.
                getSelectedItem();

        if ( jCBCriterioBusqueda.getSelectedItem().equals( "Productor" ) )
            //ejecutamos el worker
            model = worker.execute( productor, jXDPInicio.getDate(), jXDPFin.
                    getDate(), this );
        else
            //ejecutamos el worker
            model = worker.execute( establecimiento, jXDPInicio.getDate(),
                                    jXDPFin.getDate(), this );

        //asocio el modelo a la tabla
        jTResultados.setModel( model );

        //si se listan las existencias hago visible el boton para generar el listado
        if ( model instanceof TransaccionTableModel )
            jBGenerarListado.setVisible( true );
        else
            jBGenerarListado.setVisible( false );

        //finalizo los triggers de busqueda
        fireBusquedaTriggers( false );

    }//GEN-LAST:event_jBListarActionPerformed

    private void jMIDetallesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMIDetallesActionPerformed
        //obtengo las cooredenadas de la fila seleccionada
        row = jTResultados.getSelectedRow();

        //capturo el elemento seleccionado
        if ( isExistenciasSelected() ) {
            TransaccionTableModel modelo = (TransaccionTableModel)model;
            transaccion = (Transaccion)modelo.getFila( row );
        } else {
            EntityTableModel modelo = (EntityTableModel)model;
            transaccion = (Transaccion)modelo.getFila( row );
        }

        //si el elemento seleccionado es una compra
        if ( transaccion instanceof AbstractCompra ) {
            ComprasView view = new ComprasView( frame, true,
                                                (AbstractCompra)transaccion );
            view.setVisible( true );

            //informo al modelo de cambios en la tabla
            model.fireTableDataChanged();

        }

        //si el elemento seleccionado es una venta
        if ( transaccion instanceof AbstractVenta ) {
            VentasView view = new VentasView( frame, true,
                                              (AbstractVenta)transaccion );
            view.setVisible( true );

            //listo nuevamente
            jBListarActionPerformed( evt );

        }

    }//GEN-LAST:event_jMIDetallesActionPerformed

    private void jMIEliminarListaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMIEliminarListaActionPerformed
        //desvinculo el elemento eliminado del modelo
        if ( this.model instanceof EntityTableModel )
            ( (EntityTableModel)this.model ).quitarFila(
                    ( (EntityTableModel)this.model ).getFila( 
                    jTResultados.getSelectedRow() ) );
        else
            ( (TransaccionTableModel)this.model ).quitarFila(
                    ( (TransaccionTableModel)this.model ).getFila(
                    jTResultados.getSelectedRow() ) );

        model.fireTableRowsDeleted( row, row );

    }//GEN-LAST:event_jMIEliminarListaActionPerformed

    private void jMIEliminarPermanenteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMIEliminarPermanenteActionPerformed
        if ( JOptionPane.
                showConfirmDialog(
                this, String.format(
                "%s\n",
                "¿Esta seguro que desea eliminar permanentemente transacción?" ),
                "Confirmación",
                JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE )
             == JOptionPane.YES_OPTION ) {
            //o//obtengo las cooredenadas de la fila seleccionada
            row = jTResultados.getSelectedRow();

            //capturo el elemento seleccionado
            if ( isExistenciasSelected() ) {
                TransaccionTableModel modelo = (TransaccionTableModel)model;
                transaccion = (Transaccion)modelo.getFila( row );
            } else {
                EntityTableModel modelo = (EntityTableModel)model;
                transaccion = (Transaccion)modelo.getFila( row );
            }

            //si la transacción es una compra
            if ( transaccion instanceof AbstractCompra )
                //repregunto para asegurarme de que eligio correctamente
                if ( JOptionPane.showConfirmDialog(
                        this, String.format(
                        "%s\n%s\n%s\n",
                        "Esta a punto de eliminar permanentemente esta compra",
                        "Esta acción eliminara la compra y todos los animales asociados a ella",
                        "Esto unicamente es posible si ningun animal de la compra se encuentra vendido" ),
                        "Confirmación",
                        JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE )
                     == JOptionPane.YES_OPTION ) {
                    //elimino la compra en un thread aparte
                    CompraTransientWorker worker = new CompraTransientWorker( 
                            (AbstractCompra)transaccion );

                    worker.addTransientListener( this );

                    worker.execute();

                }

            //si la transacción es una Venta
            if ( transaccion instanceof AbstractVenta )
                //repregunto para asegurarme de que eligio correctamente
                if ( JOptionPane.showConfirmDialog(
                        this, String.format(
                        "%s\n%s\n%s\n",
                        "Esta a punto de eliminar permanentemente esta venta",
                        "Esta acción eliminara la venta y desafectara a todos",
                        "los animales asociados a ella" ),
                        "Confirmación",
                        JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE )
                     == JOptionPane.YES_OPTION ) {
                    //elimino la venta en un thread aparte
                    VentaTransientWorker worker = new VentaTransientWorker( 
                            (AbstractVenta)transaccion );

                    worker.addTransientListener( this );

                    worker.execute();

                }

        }

        //informo al modelo de cambios en la tabla
        model.fireTableDataChanged();

    }//GEN-LAST:event_jMIEliminarPermanenteActionPerformed

    private void jMIDeActualesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMIDeActualesActionPerformed
        //obtengo las cooredenadas de la fila seleccionada
        row = jTResultados.getSelectedRow();

        //capturo el elemento seleccionado
        if ( isExistenciasSelected() ) {
            TransaccionTableModel modelo = (TransaccionTableModel)model;
            transaccion = (Transaccion)modelo.getFila( row );
        } else {
            EntityTableModel modelo = (EntityTableModel)model;
            transaccion = (Transaccion)modelo.getFila( row );
        }

        if ( transaccion instanceof VentaHistorica ) {
            JOptionPane.showMessageDialog( this, String.format(
                    "%s\n",
                    "No puede hace historica una venta que ya es historica" ),
                                           "Error",
                                           JOptionPane.INFORMATION_MESSAGE );
            return;
        }

        //en el caso de una compraceckeamos que todos los animales de la 
        //compra esten vendidos        
        if ( transaccion instanceof Compra )
            if ( ( (Compra)transaccion ).getAnimales().size() > 0 ) {
                JOptionPane.showMessageDialog( this, String.format(
                        "%s\n", "No puede hacer historica una compra hasta no "
                                + "haber vendido todos sus animales." ),
                                               "Error",
                                               JOptionPane.INFORMATION_MESSAGE );
                return;

            }

        if ( JOptionPane.showConfirmDialog(
                this, String.format(
                "%s\n",
                "¿Esta seguro que desea hacer historica esta transacción?" ),
                "Confirmación",
                JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE )
             == JOptionPane.YES_OPTION ) {

            //elimino la transaccion
            //seteo el error a false por si ocurrio un error anteriormente
            errorTransit = false;

            //elimino el elemento en un thread aparte
            TransientWorker worker = new TransientWorker( transaccion );

            worker.addTransientListener( this );

            worker.execute();

        }

    }//GEN-LAST:event_jMIDeActualesActionPerformed

    private void jTResultadosMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jTResultadosMousePressed
        //seleccionamos la celda bajo el mouse
        if ( SwingUtilities.isRightMouseButton( evt ) )
            jTResultados.changeSelection( jTResultados.rowAtPoint( evt.
                    getPoint() ),
                                          jTResultados.columnAtPoint( evt.
                    getPoint() ),
                                          false, false );
    }//GEN-LAST:event_jTResultadosMousePressed

    private void jTResultadosMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jTResultadosMouseReleased
        jTResultadosMousePressed( evt );
    }//GEN-LAST:event_jTResultadosMouseReleased

    private void jBGenerarListadoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jBGenerarListadoActionPerformed
        DateFormat formato = new SimpleDateFormat( "dd-MM-yyyy" );
        String output = String.format( "%s-%s",
                                       formato.
                format( this.jXDPInicio.getDate() ),
                                       formato.format( this.jXDPFin.getDate() ) );

        try {

            RegistroMovimientosExistencias form =
                                           new RegistroMovimientosExistencias(
                    ( (TransaccionTableModel)this.model ).getFilas(), output );

            form.abrirEImprimir();

        } catch ( IOException IOe ) {
            //muestro el mensaje de que ha sido eliminado correctamente
            JOptionPane.showMessageDialog( this,
                                           "Ocurrió un error al intentar generar el reporte.",
                                           "Mensaje", JOptionPane.ERROR );

        } catch ( Exception e ) {
            //ignore
        }

    }//GEN-LAST:event_jBGenerarListadoActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.Box.Filler filler1;
    private javax.swing.Box.Filler filler11;
    private javax.swing.Box.Filler filler12;
    private javax.swing.Box.Filler filler13;
    private javax.swing.JButton jBGenerarListado;
    private javax.swing.JButton jBListar;
    private javax.swing.JComboBox jCBCriterioBusqueda;
    private javax.swing.JComboBox jCBTipoLista;
    private javax.swing.JLabel jLWaitIcon;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JMenu jMEliminar;
    private javax.swing.JMenuItem jMIDeActuales;
    private javax.swing.JMenuItem jMIDetalles;
    private javax.swing.JMenuItem jMIEliminarLista;
    private javax.swing.JMenuItem jMIEliminarPermanente;
    private javax.swing.JPopupMenu jPMOpciones;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPlistas;
    private javax.swing.JPanel jPresultados;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable jTResultados;
    private org.jdesktop.swingx.JXDatePicker jXDPFin;
    private org.jdesktop.swingx.JXDatePicker jXDPInicio;
    // End of variables declaration//GEN-END:variables

    /**
     * Realiza las tareas de GUI previas/posteriores a la busqueda. Esto implica
     * deshabilitar/habilitar los controles de busqueda y mostrar una animación
     * de espera.
     * @param inicio indica si se deben usar los triggers de inicio o de fin.
     */
    private void fireBusquedaTriggers( boolean inicio ) {
        //habilitamos/deshabilitamos los Combo Box
        jCBCriterioBusqueda.setEnabled( !inicio );
        jCBTipoLista.setEnabled( !inicio );

        //habilitamos/deshabilitamos los datePickers
        jXDPInicio.setEnabled( !inicio );
        jXDPFin.setEnabled( !inicio );

        //habilitamos/deshabilitamos el botón de listar
        jBListar.setEnabled( !inicio );

        //colocamos/quitamos el icono de espera
        jLWaitIcon.setIcon( inicio ? loadingIcon : null );

    }//end método fireBusquedaTriggers

    /**
     * Limpia todos los campos del formulario.
     */
    protected void limpiarPanel() {
        //cambiamos el establecimiento      
        establecimiento = frame.getEstablecimiento();

        //cambiamos el productor
        productor = frame.getProductor();

        //reseteamos la tabla 
        jTResultados.removeAll();

        //reseteamos los date pickers
        resetDatePickers();

    }//end método limpiarPanel

    /**
     * Resetea los date pickers del panel.
     */
    private void resetDatePickers() {
        Calendar cal = Calendar.getInstance();

        jXDPFin.setDate( new Date( cal.getTimeInMillis() ) );

        cal.add( Calendar.MONTH, -1 );

        jXDPInicio.setDate( new Date( cal.getTimeInMillis() ) );

    }//end método resetDatePickers

    /**
     * Setea el productor
     */
    protected void setProductor( Productor productor ) {
        this.productor = productor;
    }

    /**
     * Setea el establecimiento
     */
    protected void setEstablecimiento( Establecimiento establecimiento ) {
        this.establecimiento = establecimiento;

        //evicteamos los objetos al cambiar de establecimiento
        evictObjects();

    }

    //implementacion del metodo doneFillingTable de la interfaz TableListener
    @Override
    public void doneFillingTable() {
        //agregamos los objetos a la lista de objetos
        if ( isExistenciasSelected() )
            objetosRecuperados.addAll( ( (TransaccionTableModel)model ).
                    getFilas() );
        else
            objetosRecuperados.addAll( ( (EntityTableModel)model ).getFilas() );

        fireBusquedaTriggers( false );

    }

    //implementacion del metodo errorFillingTable de la interfaz TableListener
    @Override
    public void errorFillingTable( ExecutionException ex ) {
        //mostrar error
    }

    //implementación del método doneTransit de la interfaz TransientListener
    @Override
    public void doneTransit() {
        //si hay errores, mostramos el mensaje y salimos.
        if ( !errorTransit ) {

            //desvinculo el elemento eliminado del modelo
            if ( this.model instanceof EntityTableModel )
                ( (EntityTableModel)this.model ).quitarFila(
                        ( (EntityTableModel)this.model ).getFila( row ) );
            else
                ( (TransaccionTableModel)this.model ).quitarFila(
                        ( (TransaccionTableModel)this.model ).getFila( row ) );

            model.fireTableRowsDeleted( row, row );

            //muestro el mensaje de que ha sido eliminado correctamente
            JOptionPane.showMessageDialog( null,
                                           "Se ha eliminado la transacción satisfactoriamente",
                                           "Mensaje",
                                           JOptionPane.INFORMATION_MESSAGE );
        }

    }//end método doneTransit

    //implementación del método errorTransit de la interfaz TransientListener
    @Override
    public void errorTransit( ExecutionException ex ) {
        errorTransit = true;

        //si el error es porque habia algun animal vendido
        if ( ex.getCause() instanceof IllegalArgumentException )
            JOptionPane.showMessageDialog( null,
                                           "No se pudo eliminar la compra debido a que habia"
                                           + " al menos un animal vendido",
                                           "Error", JOptionPane.ERROR_MESSAGE );
        else
            JOptionPane.showMessageDialog( null,
                                           "Error al intentar eliminar la transacción",
                                           "Error", JOptionPane.ERROR_MESSAGE );

    }//end método errorTransit

    private boolean isExistenciasSelected() {
        return ( model instanceof TransaccionTableModel );

    }

    /**
     * Permite evictear de la cache las transacciones actualmente contenidas
     * en el modelo, para evitar que se mantengan en cache transacciones 
     * innecesarias.
     */
    public void evictObjects() {
        if ( objetosRecuperados.isEmpty() )
            return;

        EvictWorker worker = new EvictWorker( objetosRecuperados );

        worker.execute();

    }//end método evictModel

}//end clase ListadosPanel
